# classical_bot.py
# Author: Peter Sovietov

import sys, os, socket, time
import catalog, quotes

log_file = 'status.log'
state_file = 'bot_state.dat'

execfile(state_file)

quotes.q_load()

irc_log = []
msg_size = 400
irc_delay = 2

def save_state():
    f = open(state_file + '.temp', 'w')
    f.write('irc_server = ' + repr(irc_server) + '\n')
    f.write('nickname = ' + repr(nickname) + '\n')
    f.write('username = ' + repr(username) + '\n')
    f.write('realname = ' + repr(realname) + '\n')
    f.write('ch = ' + repr(ch) + '\n')
    f.close()
    os.remove(state_file)
    os.rename(state_file + '.temp', state_file)

def irc_debug(c):
    f = open(log_file, 'a')
    f.write(' '.join(c) + '\n')
    f.close()

def irc_send(s, cmd, text):
    while text:
        s.sendall(cmd + text[0:msg_size] + '\r\n')
        time.sleep(irc_delay)
        text = text[msg_size:]

def irc_last(nick, n):
    sz = len(irc_log)
    if n < 0 or n > sz:
        n = sz
    for i in range(sz - n, sz):
        irc_send(s, 'PRIVMSG %s :' % nick, irc_log[i])

def irc_command(c):
    irc_debug(c)
    if len(c) < 4:
        return
    if c[1] == 'PRIVMSG' and c[2] == ch:
        irc_log.append(c[0] + ': ' + c[3][1:])
    msg = c[3].split(' ', 1)
    if msg[0] == ':!help':
        s.sendall('PRIVMSG %s :http://code.google.com/p/classical-bot/\r\n' % ch)
    elif len(msg) == 2 and msg[0] == ':!bwv':
        irc_send(s, 'PRIVMSG %s :' % ch, catalog.bwv(msg[1]))
    elif len(msg) == 2 and msg[0] == ':!kv':
        irc_send(s, 'PRIVMSG %s :' % ch, catalog.kv(msg[1]))
    elif len(msg) == 2 and msg[0] == ':!chopin':
        irc_send(s, 'PRIVMSG %s :' % ch, catalog.chopin(msg[1]))
    elif len(msg) == 2 and msg[0] == ':!nick':
        global nickname
        s.sendall('NICK %s\r\n' % msg[1])
        nickname = msg[1]
        save_state()
    elif msg[0] == ':!last':
        if len(msg) == 2 and msg[1].isdigit():
            irc_last(c[0], int(msg[1]))
        else:
            irc_last(c[0], 10)
    elif msg[0] == ':!q':
        if len(msg) == 2:
            irc_send(s, 'PRIVMSG %s :' % ch, quotes.q_find(msg[1]))
        else:
            irc_send(s, 'PRIVMSG %s :' % ch, quotes.q_random())
    elif len(msg) == 2 and msg[0] == ':!q+':
        irc_send(s, 'PRIVMSG %s :' % ch, quotes.q_add(msg[1] + ' [' + c[0] + ']'))
    elif len(msg) == 2 and msg[0] == ':!q-' and msg[1].isdigit():
        irc_send(s, 'PRIVMSG %s :' % ch, quotes.q_remove(int(msg[1])))

def irc_parse(line):
    line = line[1:].split(' ', 3)
    line[0] = line[0].split('!')[0]
    return line
    
def irc_pong(line):
    line = line.split()
    if(line[0] == 'PING'):
        s.send('PONG %s\r\n' % line[1])

while True:
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((irc_server[0], irc_server[1]))
        fs = s.makefile('rb')
        s.sendall('NICK %s\r\n' % nickname)
        s.sendall('USER %s host server :%s\r\n' % (username, realname))
        s.sendall('JOIN %s\r\n' % ch)
        while True:
            line = fs.readline()
            if not line:
                break
            line = line.strip()
            if line[0] == ':':
                irc_command(irc_parse(line))
            else:
                irc_pong(line)
    except:
        exc_type, exc_value = sys.exc_info()[:1]
        irc_debug([str(exc_value)])
        if exc_type != socket.error:
            sys.exit()
